/**
 * @brief MCU DAC 驱动
 * @author 张勇 41204@qq.com
 * @date 2022-04
 */
 
#include "stm32f4xx_ll_gpio.h"
#include "_mcu_dac.h"


size_t mcu_dac_chcount(mcu_dac_t* dev) { return 2; }
size_t mcu_dac_max(mcu_dac_t* dev)  { return (1U << 12) - 1; }
size_t mcu_dac_bits(mcu_dac_t* dev) { return 12; }
size_t mcu_dac_bytes(mcu_dac_t* dev) { return 2; }

std_err_t mcu_dac_init(mcu_dac_t *dev, uint32_t chmask) {
    if(!dev || chmask & 0xFFFFFFFC) return STD_ERR_INVALID_ARG;
    
    LL_DAC_InitTypeDef init;
    LL_DAC_StructInit(&init);
    init.TriggerSource = LL_DAC_TRIG_SOFTWARE;
    init.OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
    init.WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
    
    // DAC通道 1 配置
    if(chmask & 0x01) {
        // 配置 PA4 为模拟模式(DAC1_OUT1)
        LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_ANALOG);
        LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_4, LL_GPIO_PULL_NO);
        LL_DAC_Init(dev->dac, LL_DAC_CHANNEL_1, &init);
        dev->chmask_init |= 0x01;
    }

    // DAC通道 2 配置
    if(chmask & 0x02) {
        // 配置 PA5 为模拟模式(DAC1_OUT2)
        LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_ANALOG);
        LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_5, LL_GPIO_PULL_NO);
        LL_DAC_Init(dev->dac, LL_DAC_CHANNEL_2, &init);
        dev->chmask_init |= 0x02;
    }
    return STD_ERR_OK;
}

std_err_t mcu_dac_start(mcu_dac_t* dev, uint32_t chmask) {
    if(!dev || chmask & 0xFFFFFFFC) return STD_ERR_INVALID_ARG;
    if((dev->chmask_init & chmask) != chmask) return STD_ERR_INVALID_STATE; // 未初始化
    if(chmask & 0x01) LL_DAC_Enable(dev->dac, LL_DAC_CHANNEL_1);
    if(chmask & 0x02) LL_DAC_Enable(dev->dac, LL_DAC_CHANNEL_2);
    return STD_ERR_OK;
}

/// @brief 停止 DAC 采样输出
std_err_t mcu_dac_stop(mcu_dac_t* dev, uint32_t chmask) {
    if(!dev || chmask & 0xFFFFFFFC) return STD_ERR_INVALID_ARG;
    if((dev->chmask_init & chmask) != chmask) return STD_ERR_INVALID_STATE; // 未初始化
    if(chmask & 0x01) LL_DAC_Disable(dev->dac, LL_DAC_CHANNEL_1);
    if(chmask & 0x02) LL_DAC_Disable(dev->dac, LL_DAC_CHANNEL_2);
    return STD_ERR_OK;
}

std_err_t mcu_dac_write(mcu_dac_t* dev, uint32_t chmask, int32_t val) {
    if(!dev || chmask & 0xFFFFFFFC) return STD_ERR_INVALID_ARG;
    if((dev->chmask_init & chmask) != chmask) return STD_ERR_INVALID_STATE; // 未初始化
    if(val >= (1U << 12)) val = (1U << 12) - 1; // 最多不超过 12 位有效值
    if(chmask & 0x01) LL_DAC_ConvertData12RightAligned(dev->dac, LL_DAC_CHANNEL_1, val);
    if(chmask & 0x02) LL_DAC_ConvertData12RightAligned(dev->dac, LL_DAC_CHANNEL_2, val);
    return STD_ERR_OK;
}
